/**
 * MongoDB 连接池模块
 * @author HalRui
 * @version 1.0.0
 * @description MongoDB连接池管理器，提供独立的MongoDB连接管理功能
 * @date 2025年9月27日
 */

const mongoose = require('mongoose');
const config = require('../env.config.json');

class MongoPool {
    constructor() {
        this.mongoConnection = null;
        this.isMongoConnected = false;
    }

    /**
     * 连接 MongoDB（使用连接池）
     */
    async connectMongoDB() {
        if (this.mongoConnection && this.isMongoConnected) {
            console.log('MongoDB 已连接，跳过...');
            return this.mongoConnection;
        }

        try {
            // MongoDB 连接池配置
            const mongoConfig = {
                maxPoolSize: 10,        // 最大连接池大小
                minPoolSize: 2,         // 最小连接池大小
                maxIdleTimeMS: 30000,   // 连接最大空闲时间
                waitQueueTimeoutMS: 5000, // 等待连接超时时间
                serverSelectionTimeoutMS: 5000, // 服务器选择超时时间
                heartbeatFrequencyMS: 10000,    // 心跳检测频率
                socketTimeoutMS: 45000,          // socket超时时间
                bufferCommands: false           // 禁用命令缓冲
            };

            const mongoUrl = config.mongodb.url + 'projects';
            
            this.mongoConnection = await mongoose.connect(mongoUrl, mongoConfig);

            // 监听 MongoDB 事件
            mongoose.connection.on('connected', () => {
                this.isMongoConnected = true;
                console.log('✅ MongoDB 连接成功！');
            });

            mongoose.connection.on('error', (err) => {
                console.error('❌ MongoDB 错误:', err);
                this.isMongoConnected = false;
            });

            mongoose.connection.on('disconnected', () => {
                this.isMongoConnected = false;
                console.log('📡 MongoDB 连接已断开');
            });

            mongoose.connection.on('reconnected', () => {
                this.isMongoConnected = true;
                console.log('🔄 MongoDB 已重新连接');
            });

            // 测试连接
            await mongoose.connection.db.admin().ping();
            console.log('🎯 MongoDB PING 测试通过');
            
            // 更新连接状态
            this.isMongoConnected = true;

            return this.mongoConnection;

        } catch (error) {
            console.error('❌ MongoDB 连接失败:', error);
            throw error;
        }
    }

    /**
     * 获取 MongoDB 连接
     */
    getMongoConnection() {
        if (!this.mongoConnection || !this.isMongoConnected) {
            throw new Error('MongoDB 未连接，请先调用 connectMongoDB()');
        }
        return this.mongoConnection;
    }

    /**
     * 获取 Mongoose 连接实例
     */
    getMongooseConnection() {
        return mongoose.connection;
    }

    /**
     * 检查连接状态
     */
    isConnected() {
        return this.isMongoConnected;
    }

    /**
     * 获取数据库统计信息
     */
    async getStats() {
        try {
            const connection = this.getMongoConnection();
            const db = connection.db;
            const stats = await db.stats();
            return stats;
        } catch (error) {
            console.error('获取数据库统计信息失败:', error);
            throw error;
        }
    }

    /**
     * 获取集合列表
     */
    async getCollections() {
        try {
            const connection = this.getMongoConnection();
            const db = connection.db;
            const collections = await db.listCollections().toArray();
            return collections.map(col => col.name);
        } catch (error) {
            console.error('获取集合列表失败:', error);
            throw error;
        }
    }

    /**
     * 执行数据库命令
     */
    async runCommand(command) {
        try {
            const connection = this.getMongoConnection();
            const db = connection.db;
            const result = await db.command(command);
            return result;
        } catch (error) {
            console.error('执行数据库命令失败:', error);
            throw error;
        }
    }

    /**
     * 健康检查
     */
    async healthCheck() {
        try {
            const start = Date.now();
            await mongoose.connection.db.admin().ping();
            const latency = Date.now() - start;
            
            return {
                status: 'healthy',
                latency: latency,
                host: mongoose.connection.host,
                port: mongoose.connection.port,
                name: mongoose.connection.name
            };
        } catch (error) {
            console.error('MongoDB 健康检查失败:', error);
            return {
                status: 'unhealthy',
                error: error.message
            };
        }
    }

    /**
     * 获取连接池统计信息
     */
    async getPoolStats() {
        try {
            const client = mongoose.connection.client;
            
            if (client && client.topology && client.topology.s && client.topology.s.pool) {
                const pool = client.topology.s.pool;
                return {
                    size: pool.size || 0,
                    available: pool.available || 0,
                    borrowed: pool.borrowed || 0,
                    pending: pool.pending || 0,
                    maxPoolSize: pool.options?.maxPoolSize || 10,
                    minPoolSize: pool.options?.minPoolSize || 2
                };
            } else {
                // 返回默认的连接池信息
                return {
                    size: 0,
                    available: 0,
                    borrowed: 0,
                    pending: 0,
                    maxPoolSize: 10,
                    minPoolSize: 2,
                    note: '连接池信息不可用，返回默认值'
                };
            }
        } catch (error) {
            console.error('获取连接池统计信息失败:', error);
            return {
                error: error.message,
                note: '获取连接池统计信息时发生错误'
            };
        }
    }

    /**
     * 断开连接
     */
    async disconnect() {
        if (this.mongoConnection && this.isMongoConnected) {
            try {
                await mongoose.disconnect();
                this.isMongoConnected = false;
                console.log('✅ MongoDB 连接已关闭');
            } catch (error) {
                console.error('❌ 关闭 MongoDB 连接失败:', error);
                throw error;
            }
        }
    }
}

module.exports = MongoPool;